package csnd.xinghe.neo4j.server.service;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import csnd.xinghe.neo4j.server.common.enums.NodeTypeEnum;
import csnd.xinghe.neo4j.server.dao.CompanyMapper;
import csnd.xinghe.neo4j.server.dto.GraphRequest;
import org.apache.commons.lang3.StringUtils;
import csnd.xinghe.neo4j.server.common.Constants;
import csnd.xinghe.neo4j.server.dao.OrgDepartmentMapper;
import csnd.xinghe.neo4j.server.dao.MainAccountMapper;
import csnd.xinghe.neo4j.server.dto.CreateGraphRequest;
import csnd.xinghe.neo4j.server.dto.DirectoryRequest;
import csnd.xinghe.neo4j.server.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Slf4j
public class GraphService {

    @Resource
    private MainAccountMapper xwMainAccountPkMapper;
    @Resource
    private CompanyMapper companyMapper;
    @Resource
    private OrgDepartmentMapper orgDepartmentMapper;

    private final Neo4jClient neo4jClient;

    public GraphService(Neo4jClient neo4jClient) {
        this.neo4jClient = neo4jClient;
    }

    // 推荐方案：使用Neo4jClient处理复合查询结果
    public GraphEntitiy getEmployeeWithRelationships(String name) {
        Map<String, Object> relationshipResult = null;
        try {
            String cypher = "MATCH (e:Person {name: $name})\n" +
                    "OPTIONAL MATCH path = (e)-[*1..1]-(related)\n" +
                    "WITH collect(DISTINCT relationships(path)) as pathRelationships,\n" +
                    "     collect(DISTINCT related)  as allNodes,\n" +
                    "     e as emp\n" +
                    "UNWIND pathRelationships as relList\n" +
                    "UNWIND relList as r\n" +
                    "WITH collect(DISTINCT r) as allRelationships,\n" +
                    "     allNodes,\n" +
                    "     emp\n" +
                    "UNWIND allNodes as node\n" +
                    "WITH allRelationships,\n" +
                    "     collect(DISTINCT node) as uniqueRelatedNodes,\n" +
                    "     emp\n" +
                    "RETURN\n" +
                    "    [r IN allRelationships | {\n" +
                    "        id: id(r),\n" +
                    "        type: type(r),\n" +
                    "        startNodeId: r.startNodeId,\n" +
                    "        endNodeId: r.endNodeId,\n" +
                    "        properties: properties(r)\n" +
                    "    }] AS edges,\n" +
                    "    {\n" +
                    "       id: id(emp),\n" +
                    "       label: head(labels(emp)),\n" +
                    "       nodeId: emp.nodeId,\n" +
                    "       name: emp.name,\n" +
                    "       properties: properties(emp)\n" +
                    "    } AS centerNode,\n" +
                    "    [n IN uniqueRelatedNodes | {\n" +
                    "        id: id(n),\n" +
                    "        label: head(labels(n)),\n" +
                    "        nodeId: n.nodeId,\n" +
                    "        name: n.name,\n" +
                    "        properties: properties(n)\n" +
                    "    }] AS nodes";

            relationshipResult = neo4jClient.query(cypher)
                    .bind(name).to("name")
                    .fetch()
                    .first()
                    .orElse(new HashMap<>());
        } catch (Exception e) {
            log.error("图查询失败: {}", e);
            throw new RuntimeException("图查询失败: " + e.getMessage(), e);
        }
        return convertToGraphDTO(relationshipResult);
    }


    public GraphEntitiy getCompanyWithRelationships(String name) {
        Map<String, Object> relationshipResult = null;
        try {

            String cypher = "MATCH (c:Company {name: $name})\n" +
                    "OPTIONAL MATCH path = (c)-[*1..1]-(related)\n" +
                    "WITH collect(DISTINCT relationships(path)) as pathRelationships,\n" +
                    "     collect(DISTINCT related) + [c] as allNodes,  // 将起始节点e添加到节点列表中\n" +
                    "     c as emp\n" +
                    "UNWIND pathRelationships as relList\n" +
                    "UNWIND relList as r\n" +
                    "WITH collect(DISTINCT r) as allRelationships,\n" +
                    "     allNodes,\n" +
                    "     emp\n" +
                    "UNWIND allNodes as node\n" +
                    "WITH allRelationships,\n" +
                    "     collect(DISTINCT node) as uniqueRelatedNodes,  // 确保节点去重\n" +
                    "     emp\n" +
                    "RETURN\n" +
                    "    [r IN allRelationships | {\n" +
                    "        id: id(r),\n" +
                    "        type: type(r),\n" +
                    "        startNodeId: r.startNodeId,\n" +
                    "        endNodeId: r.endNodeId,\n" +
                    "        properties: properties(r)\n" +
                    "    }] AS relationships,\n" +
                    "    [n IN uniqueRelatedNodes | {\n" +
                    "        id: id(n),\n" +
                    "        label: head(labels(n)),\n" +
                    "        nodeId: n.nodeId,\n" +
                    "        name: n.name,\n" +
                    "        properties: properties(n)\n" +
                    "    }] AS relatedNodes";
            relationshipResult = neo4jClient.query(cypher)
                    .bind(name).to("name")
                    .fetch()
                    .first()
                    .orElse(new HashMap<>());
        } catch (Exception e) {
            log.error("图查询失败: {}", e);
            throw new RuntimeException("图查询失败: " + e.getMessage(), e);
        }
        return convertToGraphDTO(relationshipResult);
    }


    public GraphEntitiy getDirectGraph(String nodeId) {
        Map<String, Object> relationshipResult = null;
        try {
            String cypher = "MATCH (e {nodeId: $nodeId})\n" +
                    "OPTIONAL MATCH path = (e)-[*1..1]-(related)\n" +
                    "WITH collect(DISTINCT relationships(path)) as pathRelationships,\n" +
                    "     collect(DISTINCT related)  as allNodes,\n" +
                    "     e as emp\n" +
                    "UNWIND pathRelationships as relList\n" +
                    "UNWIND relList as r\n" +
                    "WITH collect(DISTINCT r) as allRelationships,\n" +
                    "     allNodes,\n" +
                    "     emp\n" +
                    "UNWIND allNodes as node\n" +
                    "WITH allRelationships,\n" +
                    "     collect(DISTINCT node) as uniqueRelatedNodes,\n" +
                    "     emp\n" +
                    "RETURN\n" +
                    "    [r IN allRelationships | {\n" +
                    "        id: id(r),\n" +
                    "        label: type(r),\n" +
                    "        source: r.startNodeId,\n" +
                    "        target: r.endNodeId,\n" +
                    "        properties: properties(r)\n" +
                    "    }] AS edges,\n" +
                    "    {\n" +
                    "       id: id(emp),\n" +
                    "       label: head(labels(emp)),\n" +
                    "       nodeId: emp.nodeId,\n" +
                    "       name: emp.name,\n" +
                    "       properties: properties(emp)\n" +
                    "    } AS centerNode,\n" +
                    "    [n IN uniqueRelatedNodes | {\n" +
                    "        id: id(n),\n" +
                    "        label: head(labels(n)),\n" +
                    "        nodeId: n.nodeId,\n" +
                    "        name: n.name,\n" +
                    "        properties: properties(n)\n" +
                    "    }] AS nodes";

            relationshipResult = neo4jClient.query(cypher)
                    .bind(nodeId).to("nodeId")
                    .fetch()
                    .first()
                    .orElse(new HashMap<>());
        } catch (Exception e) {
            log.error("图查询失败: {}", e);
            throw new RuntimeException("图查询失败: " + e.getMessage(), e);
        }
        return convertToGraphDTO(relationshipResult);
    }


    @Transactional
    public Map<String, Object> createGraph(CreateGraphRequest request) {
        Map<String, Object> result = new HashMap<>();
        try {
            // 创建节点
            if (!CollectionUtils.isEmpty(request.getNodes())) {
                for (Node node : request.getNodes()) {
                    createNode(node);
                }
            }
            // 创建关系
            if (!CollectionUtils.isEmpty(request.getRelationships())) {
                for (Relationship relationship : request.getRelationships()) {
                    createRelationship(relationship);
                }
            }
            result.put("message", Constants.SUCCESS_MESSAGE);
            result.put("code", Constants.SUCCESS_CODE);
        } catch (Exception e) {
            log.error("图数据创建失败: {}", e);
            throw new RuntimeException("图数据创建失败: " + e.getMessage(), e);
        }
        return result;
    }


    public List<EdgeEntity> getNodeRelation(String firstNodeId, String secondNodeId) {
        List<Map<String, Object>> result = null;
        try {
            String cypher = "MATCH (a {nodeId: $firstNodeId})-[r]-(b {nodeId: $secondNodeId})\n" +
                    "RETURN \n" +
                    "    id(r) AS id,\n" +
                    "    type(r) AS label,\n" +
                    "    properties(r) AS properties,\n" +
                    "    r.startNodeId AS source,\n" +  // 从关系属性获取
                    "    r.endNodeId AS target";          // 从关系属性获取

            result = neo4jClient.query(cypher)
                    .bind(firstNodeId).to("firstNodeId")
                    .bind(secondNodeId).to("secondNodeId")
                    .fetch()
                    .all()
                    .stream()
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("图查询失败: {}", e);
            throw new RuntimeException("图查询失败: " + e.getMessage(), e);
        }
        return convertToRelationsDTO(result);
    }


























    @Transactional
    public Map<String, Object> updateGraph(CreateGraphRequest request) {
        Map<String, Object> result = new HashMap<>();
        try {
            //  更新节点
            if (!CollectionUtils.isEmpty(request.getNodes())) {
                updateNodesWithMerge(request.getNodes());
            }
            // 更新关系
            if (!CollectionUtils.isEmpty(request.getRelationships())) {
                updateRelationshipsWithReplace(request.getRelationships());
            }
            result.put("message", Constants.SUCCESS_MESSAGE);
            result.put("code", Constants.SUCCESS_CODE);
        } catch (Exception e) {
            log.error("图数据修改失败: {}", e);
            throw new RuntimeException("图数据修改失败: " + e.getMessage(), e);
        }
        return result;
    }


    /**
     * 使用MERGE方式更新节点（避免删除现有节点）
     *
     * @param nodes 节点列表
     */
    private void updateNodesWithMerge(List<Node> nodes) {
        Map<String, List<Node>> nodesByType = nodes.stream()
                .collect(Collectors.groupingBy(Node::getType));

        for (Map.Entry<String, List<Node>> entry : nodesByType.entrySet()) {
            String nodeType = entry.getKey();
            List<Node> nodeList = entry.getValue();

            String cypher = String.format(
                    "UNWIND $nodesData as nodeData\n" +
                            "MERGE (n:%s {nodeId: nodeData.nodeId})\n" +
                            "SET n = nodeData.properties",
                    nodeType);

            List<Map<String, Object>> nodesData = nodeList.stream()
                    .map(this::prepareNodeData)
                    .collect(Collectors.toList());

            Map<String, Object> parameters = new HashMap<>();
            parameters.put("nodesData", nodesData);

            neo4jClient.query(cypher)
                    .bindAll(parameters)
                    .run();
        }
    }


    public List<HomePageSearchNodeEntity> homePageSearch(String name) {
        List<HomePageSearchNodeEntity> list = new ArrayList<>();
        //搜索员工
        LambdaQueryWrapper<MainAccountDo> accountWrapper = new LambdaQueryWrapper<>();
        //判断name是拼音还是汉字
        if(isChinese(name)){
            // 如果是汉字，模糊搜索名称
            accountWrapper.like(MainAccountDo::getEmpName, name);
        }else{
            // 如果是拼音，模糊搜索email
            accountWrapper.like(MainAccountDo::getEmail, name);
        }
        List<MainAccountDo> personList = xwMainAccountPkMapper.selectList(accountWrapper);

        for (MainAccountDo mainAccountDo : personList) {
            String deptId = mainAccountDo.getDeptId();
            LambdaQueryWrapper<OrgDepartmentDo> orgDepartmentWrapper1 = new LambdaQueryWrapper<>();
            orgDepartmentWrapper1.eq(OrgDepartmentDo::getId, deptId);
            OrgDepartmentDo orgDepartmentDo1 = orgDepartmentMapper.selectOne(orgDepartmentWrapper1);

            LambdaQueryWrapper<OrgDepartmentDo> orgDepartmentWrapper2 = new LambdaQueryWrapper<>();
            orgDepartmentWrapper2.eq(OrgDepartmentDo::getOrgCode, orgDepartmentDo1.getParentOrgCode());
            OrgDepartmentDo orgDepartmentDo2 = orgDepartmentMapper.selectOne(orgDepartmentWrapper2);

            HomePageSearchNodeEntity nodeEntity = HomePageSearchNodeEntity.builder()
                    .nodeId(mainAccountDo.getEmpCode())
                    .type("person")
                    .name(mainAccountDo.getEmpName())
                    //设置组织名称
                    .organization(orgDepartmentDo2.getOrgName() + "/" + orgDepartmentDo1.getOrgName())
                    .build();
            list.add(nodeEntity);
        }

        //搜索企业
        LambdaQueryWrapper<CompanyDo> companyWrapper = new LambdaQueryWrapper<>();
        companyWrapper.like(CompanyDo::getName, name);
        List<CompanyDo> companyList = companyMapper.selectList(companyWrapper);
        for (CompanyDo company : companyList) {
            HomePageSearchNodeEntity nodeEntity = HomePageSearchNodeEntity.builder()
                    .nodeId(String.valueOf(company.getId()))
                    .type("company")
                    .name(company.getName())
                    .creditCode(company.getCreditCode())
                    .build();
            list.add(nodeEntity);
        }
        return list;
    }



    /**
     * 判断字符串是否包含中文
     * @param str 待判断的字符串
     * @return true表示包含中文，false表示不包含中文
     */
    private boolean isChinese(String str) {
        if (str == null || str.isEmpty()) {
            return false;
        }
        // 使用正则表达式判断是否包含中文字符
        return str.matches(".*[\u4e00-\u9fa5]+.*");
    }


//    public DirectoryResultEntity directory(DirectoryRequest request) {
//        DirectoryResultEntity result = new DirectoryResultEntity();
//        GraphEntitiy firstGraph = new GraphEntitiy();
//        GraphEntitiy secondGraph = new GraphEntitiy();
//        GraphEntitiy thirdGraph = new GraphEntitiy();
//        //中心节点id
//        String firstCenterNodeId = new String();
//        String secondCenterNodeId = new String();
//        String thirdCenterNodeId  = new String();
//        //关联节点id
//        List<String> firstCorrelationNodeIds = new ArrayList<>();
//        List<String> secondCorrelationNodeIds = new ArrayList<>();
//        List<String> thirdCorrelationNodeIds = new ArrayList<>();
//        //二级节点id( 一级节点
//        List<String> secondLevelNodeIds = new ArrayList<>();
//        List<String> thirdLevelNodeIds = new ArrayList<>();
//
//        //一级关联
//        if(StringUtils.isNotBlank(request.getFirstNodeId())){
//            firstGraph = getDirectGraph(request.getFirstNodeId());
//            //获取一级节点/一级关联节点（一级关联节点 = 一级节点）
//            List<NodeEntity> firstLevelNodes = firstGraph.getNodes();
//            firstCenterNodeId = firstGraph.getCenterNode().getId();
//            firstCorrelationNodeIds = firstLevelNodes.stream().map(NodeEntity::getId).collect(Collectors.toList());
//            //获取一级节点的数量
//            long personCount = firstLevelNodes.stream()
//                    .filter(node -> "Person".equals(node.getLabel()))
//                    .count();
//            long companyCount = firstLevelNodes.stream()
//                    .filter(node -> "Company".equals(node.getLabel()))
//                    .count();
//            DirectoryNodeDataEntity directoryNodeData = DirectoryNodeDataEntity.builder()
//                    .personCount(personCount)
//                    .companyCount(companyCount)
//                    .build();
//
//            //获取一级关系
//            List<EdgeEntity> firstLevelEdges = firstGraph.getEdges();
//            //获取一级关系的数量
//            Map<String, Long> directoryRelationshipsData = firstLevelEdges.stream()
//                    .collect(Collectors.groupingBy(EdgeEntity::getLabel, Collectors.counting()));
//            DirectoryLevelDataEntity build = DirectoryLevelDataEntity.builder()
//                    .nodes(directoryNodeData)
//                    .edges(directoryRelationshipsData)
//                    .build();
//            result.setFirstLevel(build);
//        }
//
//        //二级关联
//        if(StringUtils.isNotBlank(request.getSecondNodeId())){
//            //获取二级中心节点的直接图
//            secondGraph = getDirectGraph(request.getSecondNodeId());
//            //获取二级关联节点
//            List<NodeEntity> nodes = secondGraph.getNodes();
//            secondCenterNodeId = secondGraph.getCenterNode().getId();
//            secondCorrelationNodeIds = nodes.stream().map(NodeEntity::getId).collect(Collectors.toList());
//
//            //获取二级节点(独属于二级中心节点，而不属于一级中心节点的节点): 二级关联节点 - 一级关联节点 - 一级中心节点
//            List<NodeEntity> secondLevelNodes = new ArrayList<>();
//                //过滤id集合
//            List<String> filterIds = new  ArrayList<>();
//            filterIds.add(firstCenterNodeId);
//            filterIds.addAll(firstCorrelationNodeIds);
//                //二级关联节点过滤一级关联节点和一级中心节点
//            secondLevelNodes = nodes.stream()
//                    .filter(node -> !filterIds.contains(node.getId()))
//                    .collect(Collectors.toList());
//            //获取二级节点的数量
//            long personCount = secondLevelNodes.stream()
//                    .filter(node -> "Person".equals(node.getLabel()))
//                    .count();
//            long companyCount = secondLevelNodes.stream()
//                    .filter(node -> "Company".equals(node.getLabel()))
//                    .count();
//            DirectoryNodeDataEntity directoryNodeData = DirectoryNodeDataEntity.builder()
//                    .personCount(personCount)
//                    .companyCount(companyCount)
//                    .build();
//
//            /**
//             * 获取二级关系: [ 二级关联关系 - ( 一级中心节点和二级中心节点的关系 )] + [ 二级节点 和 ( 一级关联节点 - 二级中心节点 ) 的关系 ]
//             *
//             * 注意：
//             *      1.二级节点属于二级中心节点，跟一级中心节点无关联，因此不需要考虑二级节点和一级中心节点的关系
//             */
//
//
//            List<EdgeEntity> secondLevelEdges = new ArrayList<>();
//                //获取二级关联关系
//            List<EdgeEntity> edges = secondGraph.getEdges();
//                //获取一级中心节点和二级中心节点关系
//            List<EdgeEntity> firstCenterAndSecondCenterEdg = getNodeRelation(firstCenterNodeId, secondCenterNodeId);
//                //二级关联关系 - ( 一级中心节点和二级中心节点的关系 )
//            secondLevelEdges.addAll(edges.stream().filter(edge -> !firstCenterAndSecondCenterEdg.contains(edge)).collect(Collectors.toList()));
//
//
//                //获取二级节点的nodeId集合
//            secondLevelNodeIds = secondLevelNodes.stream().map(node -> node.getId()).collect(Collectors.toList());
//                //获取 ( 一级中心节点 + 一级关联节点 - 二级中心节点 )的nodeId集合
//            List<String> ids = new ArrayList<>();
//            ids.add(firstCenterNodeId);
//            String finalSecondCenterNodeId = secondCenterNodeId;
//            ids.addAll(firstCorrelationNodeIds.stream().filter(nodeId -> !finalSecondCenterNodeId.equals(nodeId)).collect(Collectors.toList()));
//                //二级节点 和 (一级中心节点 + 一级关联节点 - 二级中心节点) 的关系
//            for (String secondLevelNodeId : secondLevelNodeIds) {
//                for (String nodeId : ids) {
//                    secondLevelEdges.addAll(getNodeRelation(secondLevelNodeId, nodeId));
//                }
//            }
//            //获取二级关系的数量
//            Map<String, Long> directoryRelationshipsData = secondLevelEdges.stream()
//                    .collect(Collectors.groupingBy(EdgeEntity::getLabel, Collectors.counting()));
//            DirectoryLevelDataEntity build = DirectoryLevelDataEntity.builder()
//                    .nodes(directoryNodeData)
//                    .edges(directoryRelationshipsData)
//                    .build();
//            result.setSecondLevel(build);
//        }
//        if(StringUtils.isNotBlank(request.getThirdNodeId())){
//            // 获取三级中心节点的直接图
//            thirdGraph = getDirectGraph(request.getThirdNodeId());
//            // 获取三级关联节点
//            List<NodeEntity> thirdNodes = thirdGraph.getNodes();
//            thirdCenterNodeId = thirdGraph.getCenterNode().getId();
//            thirdCorrelationNodeIds = thirdNodes.stream().map(NodeEntity::getId).collect(Collectors.toList());
//
//
//            /**
//             * 获取三级节点(独属于三级中心节点，而不属于一级中心和二级中心节点的节点): 三级关联节点 - 二级关联节点 - 一级关联节点
//             * 注意：
//             *      1.三级节点由于独属于三级中心节点，跟一级中心节点和二级中心节点无关联，因此三级关联节点需要过滤二级中心节点
//             *      2.三级关联节点不需要过滤一级中心节点，因为三级中心节点不可能连接一级中心节点
//             *      3.一级关联节点包含二级中心节点，二级关联节点包含一级中心和三级中心，因此三级节点 = 三级关联节点 - 二级关联节点 - 一级关联节点
//             */
//            List<NodeEntity> thirdLevelNodes = new ArrayList<>();
//            List<String> filterIds = new ArrayList<>();
//            filterIds.addAll(firstCorrelationNodeIds);
//            filterIds.addAll(secondCorrelationNodeIds);
//                //三级关联节点过滤一级关联节点和二级关联节点
//            thirdLevelNodes = thirdNodes.stream()
//                    .filter(node -> !filterIds.contains(node.getId()))
//                    .collect(Collectors.toList());
//            //获取三级节点的数量
//            long personCount = thirdLevelNodes.stream()
//                    .filter(node -> "Person".equals(node.getLabel()))
//                    .count();
//            long companyCount = thirdLevelNodes.stream()
//                    .filter(node -> "Company".equals(node.getLabel()))
//                    .count();
//            DirectoryNodeDataEntity directoryNodeData = DirectoryNodeDataEntity.builder()
//                    .personCount(personCount)
//                    .companyCount(companyCount)
//                    .build();
//
//
//            /**
//             * 获取三级关系: [ 三级关联关系 - ( 二级中心节点和三级中心节点的关系)] + [ 三级节点 和 ( ( 二级节点 - 三级中心节点) + ( 一级节点 - 二级中心节点 ) ) ]
//             * 注意：
//             *      1.三级关系需要包含三级节点和二级节点的关系，三级节点和一级节点的关系
//             *      2.由于二级节点可能包含三级中心节点，因此需要过滤掉三级中心节点，因为三级节点和三级中心节点的关系已经计算过了
//             *      3.由于一级节点本身包含二级中心节点，因此需要过滤掉二级中心节点，但是由于三级节点本身独属于三级中心节点，因此不过滤二级中心节点也可以
//             */
//            List<EdgeEntity> thirdLevelEdges = new ArrayList<>();
//                // 获取三级关联关系
//            List<EdgeEntity> thirdEdges = thirdGraph.getEdges();
//                // 获取二级中心节点和三级中心节点关系
//            List<EdgeEntity> secondCenterAndThirdCenterEdge = getNodeRelation(secondCenterNodeId, thirdCenterNodeId);
//                // 三级关联关系 - (二级中心节点和三级中心节点的关系)
//            thirdLevelEdges.addAll(thirdEdges.stream()
//                    .filter(edge -> !secondCenterAndThirdCenterEdge.contains(edge))
//                    .collect(Collectors.toList()));
//
//            // 获取三级节点的nodeId集合
//           thirdLevelNodeIds = thirdLevelNodes.stream()
//                    .map(NodeEntity::getId)
//                    .collect(Collectors.toList());
//           // 获取关联节点集合: ( 二级节点 - 三级中心节点) + ( 一级节点 - 二级中心节点 )
//           List<String> relatedNodeIds = new ArrayList<>();
//                // 二级节点过滤三级中心节点
//            String finalThirdCenterNodeId = thirdCenterNodeId;
//            relatedNodeIds.addAll(secondLevelNodeIds.stream()
//                   .filter(nodeId -> !finalThirdCenterNodeId.equals(nodeId))
//                   .collect(Collectors.toList()));
//                //一级节点过滤二级中心节点
//            String finalSecondCenterNodeId1 = secondCenterNodeId;
//            relatedNodeIds.addAll(firstCorrelationNodeIds.stream()
//                    .filter(nodeId -> !finalSecondCenterNodeId1.equals(nodeId))
//                    .collect(Collectors.toList()));
//            // 获取三级节点和相关节点的关系
//            for (String thirdLevelNodeId : thirdLevelNodeIds) {
//                for (String relatedNodeId : relatedNodeIds) {
//                    thirdLevelEdges.addAll(getNodeRelation(thirdLevelNodeId, relatedNodeId));
//                }
//            }
//            // 获取三级关系的数量
//            Map<String, Long> directoryRelationshipsData = thirdLevelEdges.stream()
//                    .collect(Collectors.groupingBy(EdgeEntity::getLabel, Collectors.counting()));
//            DirectoryLevelDataEntity build = DirectoryLevelDataEntity.builder()
//                    .nodes(directoryNodeData)
//                    .edges(directoryRelationshipsData)
//                    .build();
//            result.setThirdLevel(build);
//        }
//        return result;
//    }


    public DirectoryResultEntity directory(DirectoryRequest request) {
        DirectoryResultEntity result = new DirectoryResultEntity();
        GraphEntitiy firstGraph = new GraphEntitiy();
        GraphEntitiy secondGraph = new GraphEntitiy();
        GraphEntitiy thirdGraph = new GraphEntitiy();
        //一级关联
        if (StringUtils.isNotBlank(request.getFirstNodeId())) {
            firstGraph = getDirectGraph(request.getFirstNodeId());
            //获取一级节点/一级关联节点（一级关联节点 = 一级节点）
            List<NodeEntity> firstLevelNodes = firstGraph.getNodes();
            //获取一级节点的数量
            long personCount = firstLevelNodes.stream()
                    .filter(node -> "Person".equals(node.getLabel()))
                    .count();
            long companyCount = firstLevelNodes.stream()
                    .filter(node -> "Company".equals(node.getLabel()))
                    .count();
            DirectoryNodeDataEntity directoryNodeData = DirectoryNodeDataEntity.builder()
                    .personCount(personCount)
                    .companyCount(companyCount)
                    .build();
            //获取一级关系
            List<EdgeEntity> firstLevelEdges = firstGraph.getEdges();
            //获取一级关系的数量
            Map<String, Long> directoryRelationshipsData = firstLevelEdges.stream()
                    .collect(Collectors.groupingBy(EdgeEntity::getLabel, Collectors.counting()));
            DirectoryLevelDataEntity build = DirectoryLevelDataEntity.builder()
                    .nodes(directoryNodeData)
                    .relationships(directoryRelationshipsData)
                    .build();
            result.setFirstLevel(build);
        }

        //二级关联
        if (StringUtils.isNotBlank(request.getSecondNodeId())) {
            secondGraph = getDirectGraph(request.getSecondNodeId());
            //获取二级节点/一级关联节点（一级关联节点 = 一级节点）
            List<NodeEntity> secondLevelNodes = secondGraph.getNodes();
            //获取二级节点的数量
            long personCount = secondLevelNodes.stream()
                    .filter(node -> "Person".equals(node.getLabel()))
                    .count();
            long companyCount = secondLevelNodes.stream()
                    .filter(node -> "Company".equals(node.getLabel()))
                    .count();
            DirectoryNodeDataEntity directoryNodeData = DirectoryNodeDataEntity.builder()
                    .personCount(personCount)
                    .companyCount(companyCount)
                    .build();


            //获取二级关系
            List<EdgeEntity> secondLevelEdges = secondGraph.getEdges();
            //二级关系中过滤一级中心节点和二级中心节点的关系
            List<EdgeEntity> firstCenterAndSecondCenterEdg = getNodeRelation(request.getFirstNodeId(), request.getSecondNodeId());
            List<EdgeEntity>  filterSecondLevelEdges = secondLevelEdges.stream().filter(edge -> !firstCenterAndSecondCenterEdg.contains(edge)).collect(Collectors.toList());


            //获取二级关系的数量
            Map<String, Long> directoryRelationshipsData = filterSecondLevelEdges.stream()
                    .collect(Collectors.groupingBy(EdgeEntity::getLabel, Collectors.counting()));

            DirectoryLevelDataEntity build = DirectoryLevelDataEntity.builder()
                    .nodes(directoryNodeData)
                    .relationships(directoryRelationshipsData)
                    .build();
            result.setSecondLevel(build);
        }


        //三级关联
        if (StringUtils.isNotBlank(request.getThirdNodeId())) {
            thirdGraph = getDirectGraph(request.getThirdNodeId());
            //获取三级节点/一级关联节点（一级关联节点 = 一级节点）
            List<NodeEntity> thirdLevelNodes = thirdGraph.getNodes();
            //获取三级节点的数量
            long personCount = thirdLevelNodes.stream()
                    .filter(node -> "Person".equals(node.getLabel()))
                    .count();
            long companyCount = thirdLevelNodes.stream()
                    .filter(node -> "Company".equals(node.getLabel()))
                    .count();
            DirectoryNodeDataEntity directoryNodeData = DirectoryNodeDataEntity.builder()
                    .personCount(personCount)
                    .companyCount(companyCount)
                    .build();

            //获取三级关系
            List<EdgeEntity> thirdLevelEdges = thirdGraph.getEdges();
            //三级关系中过滤二级中心节点和三级中心节点的关系
            List<EdgeEntity> secondCenterAndThirdCenterEdg = getNodeRelation(request.getSecondNodeId(), request.getThirdNodeId());
            List<EdgeEntity>  filterThirdLevelEdges = thirdLevelEdges.stream().filter(edge -> !secondCenterAndThirdCenterEdg.contains(edge)).collect(Collectors.toList());

            //获取三级关系的数量
            Map<String, Long> directoryRelationshipsData = filterThirdLevelEdges.stream()
                    .collect(Collectors.groupingBy(EdgeEntity::getLabel, Collectors.counting()));

            DirectoryLevelDataEntity build = DirectoryLevelDataEntity.builder()
                    .nodes(directoryNodeData)
                    .relationships(directoryRelationshipsData)
                    .build();
            result.setThirdLevel(build);
        }
        return result;
    }




    public GraphResultEntity graph(@RequestBody GraphRequest request) {
        GraphResultEntity result = new GraphResultEntity();
        //一级查询
        if(StringUtils.isNotBlank(request.getFirstLevel().getNodeId()) && StringUtils.isBlank(request.getSecondLevel().getNodeId())){
            result = firstLevelGraph(request);

        }
        //二级查询
        if(StringUtils.isNotBlank(request.getSecondLevel().getNodeId()) && StringUtils.isBlank(request.getThirdLevel().getNodeId())){
            result = secondLevelGraph(request);
        }

        //三级查询
        if(StringUtils.isNotBlank(request.getThirdLevel().getNodeId())){
            result = thirdLevelGraph(request);
        }
        return result;
    }


    /**
     * 一级图谱查询
     * @param request
     * @return
     */
    private GraphResultEntity firstLevelGraph(GraphRequest request) {
        GraphLevelConditionsEntity firstCondition = request.getFirstLevel();
        //获取一级图谱
        GraphEntitiy firstGraph = getDirectGraph(firstCondition.getNodeId());
        NodeEntity firstCenterNode = firstGraph.getCenterNode();
        //获取前置一级节点和一级关系
        List<NodeEntity> firstCorrelationNodes = firstGraph.getNodes();
        List<EdgeEntity> firstCorrelationEdges = firstGraph.getEdges();
        //根据条件过滤，获取一级节点和一级关系
        List<NodeEntity> firstLevelNodes = getNodebyCondition(firstCondition, firstCorrelationNodes);
        List<EdgeEntity> firstLevelEdges = getEdgebyCondition(firstCondition, firstCorrelationEdges);
        //根据一级节点过滤一级关系
        List<String> firstLevelNodeIds = firstLevelNodes.stream().map(node -> node.getId()).collect(Collectors.toList());
        firstLevelEdges = firstLevelEdges.stream().filter(edge -> firstLevelNodeIds.contains(edge.getSource()) || firstLevelNodeIds.contains(edge.getTarget())).collect(Collectors.toList());


        //由于可能存在有节点但是没有关系的可能，也需要根据关系过滤节点
        List<String> nodeIdsCorrelationEdge
                = firstLevelEdges.stream()
                .flatMap(edge -> Stream.of(edge.getSource(), edge.getTarget()))
                .distinct()
                .collect(Collectors.toList());
        firstLevelNodes = firstLevelNodes.stream().filter(node -> nodeIdsCorrelationEdge.contains(node.getId())).collect(Collectors.toList());


        //补充属性
        firstLevelNodes.stream().forEach(node -> {node.setLevel(1); firstCenterNode.setType("circle");});
        firstLevelEdges.stream().forEach(edge -> {edge.setLevel(1); edge.setType("line");});

        //一级节点中补充一级中心节点
        firstCenterNode.setIsCenter(true);
        firstCenterNode.setLevel(0);
        firstCenterNode.setType("circle");
        firstLevelNodes.add(firstCenterNode);

        GraphResultEntity resultEntity = new GraphResultEntity();
        resultEntity.setFirstLevel(GraphLevelDataEntity.builder()
                .nodes(firstLevelNodes)
                .edges(firstLevelEdges)
                .build());
        return resultEntity;
    }


    /**
     * 二级图谱查询
     * @param request
     * @return
     */
    private GraphResultEntity secondLevelGraph(GraphRequest request) {
        //获取条件
        GraphLevelConditionsEntity firstCondition = request.getFirstLevel();
        GraphLevelConditionsEntity secondCondition = request.getSecondLevel();
        //准备图
        GraphEntitiy firstGraph = getDirectGraph(firstCondition.getNodeId());
        GraphEntitiy secondGraph = getDirectGraph(secondCondition.getNodeId());
        //准备一级和二级的关联节点和关联关系
        List<NodeEntity> firstCorrelationNodes = firstGraph.getNodes();
        List<NodeEntity> secondCorrelationNodes = secondGraph.getNodes();
        List<EdgeEntity> firstCorrelationEdges = firstGraph.getEdges();
        List<EdgeEntity> secondCorrelationEdges = secondGraph.getEdges();
        //准备一级中心节点和二级中心节点
        NodeEntity firstCenterNode = firstGraph.getCenterNode();
        NodeEntity secondCenterNode = secondGraph.getCenterNode();


        /**
         * 准备前置的一级节点和一级关系，然后根据条件过滤获取真正的一级节点和一级关系
         * 步骤：
         *      前置一级节点 = 一级关联节点 - 二级中心节点
         *      一级节点 = 前置一级节点根据条件过滤
         *
         *      前置一级关系 = 前置一级关系1 + 前置一级关系2
         *      前置一级关系1 = 一级关联关系 - 一级中心节点和二级中心节点的关系
         *          注意：
         *              一级前置关系1需要根据一级节点过滤
         *      前置一级关系2 = 二级节点和一级中心节点的关系
         *      一级关系 = 前置一级关系根据条件过滤
         */
        //获取前置一级节点
        List<NodeEntity> preFirstLevelNodes = firstCorrelationNodes.stream().filter(node -> !node.getId().equals(secondCenterNode.getId())).collect(Collectors.toList());
        //获取一级节点，根据条件过滤
        List<NodeEntity> firstLevelNodes = getNodebyCondition(firstCondition, preFirstLevelNodes);
        //获取前置一级关系1
        List<EdgeEntity> firstCenterAndSecondCenterEdg = getNodeRelation(firstCenterNode.getId(), secondCenterNode.getId());
        List<EdgeEntity> preFirstLevelEdge1 = firstCorrelationEdges.stream().filter(edge -> !firstCenterAndSecondCenterEdg.contains(edge)).collect(Collectors.toList());
        //根据一级节点过滤前置一级关系1
        List<String> firstLevelNodeIds = firstLevelNodes.stream().map(node -> node.getId()).collect(Collectors.toList());
        preFirstLevelEdge1 = preFirstLevelEdge1.stream().filter(edge -> firstLevelNodeIds.contains(edge.getSource()) || firstLevelNodeIds.contains(edge.getTarget())).collect(Collectors.toList());




        /**
         * 准备前置二级节点和二级级关系，然后根据条件过滤获取真正的二级节点和二级关系
         * 步骤：
         *      前置二级节点 = 二级关联节点 - 一级中心节点 - 一级节点
         *      二级节点 = 前置二级节点根据条件过滤
         *
         *      前置二级关系 = 前置二级关系1 + 前置二级关系2
         *      前置二级关系1 = 二级关联关系 - 一级中心节点和二级中心节点的关系
         *            注意：
         *                前置二级关系1根据二级节点过滤
         *      前置二级关系2 = 一级节点和二级中心节点的关系
         *      二级关系 = 前置二级关系根据条件过滤
         */
        //获取前置二级节点
        List<NodeEntity> preSecondLevelNodes = secondCorrelationNodes.stream().filter(node -> !node.getId().equals(firstCenterNode.getId()) && !firstLevelNodes.contains(node)).collect(Collectors.toList());
        //获取二级节点，根据条件过滤
        List<NodeEntity> secondLevelNodes = getNodebyCondition(secondCondition, preSecondLevelNodes);


        //获取前置二级关系1 = 获取二级关联关系 - 一级中心节点和二级中心节点的关系
        List<EdgeEntity> preSecondLevelEdge1 = secondCorrelationEdges.stream().filter(edge -> !firstCenterAndSecondCenterEdg.contains(edge)).collect(Collectors.toList());
        //根据二级节点过滤前置二级关系1
        List<String> secondLevelNodeIds = secondLevelNodes.stream().map(node -> node.getId()).collect(Collectors.toList());
        preSecondLevelEdge1 = preSecondLevelEdge1.stream().filter(edge -> secondLevelNodeIds.contains(edge.getSource()) || secondLevelNodeIds.contains(edge.getTarget())).collect(Collectors.toList());

        //获取前置二级关系2 = 一级节点和二级中心节点的关系
        List<EdgeEntity> preSecondLevelEdge2 = new ArrayList<>();
        for (NodeEntity firstLevelNode : firstLevelNodes) {
            preSecondLevelEdge2.addAll(getNodeRelation(firstLevelNode.getId(), secondCenterNode.getId()));
        }
        List<EdgeEntity>  preSecondLevelEdges = new ArrayList<>();
        preSecondLevelEdges.addAll(preSecondLevelEdge1);
        preSecondLevelEdges.addAll(preSecondLevelEdge2);
        //前置关系根据条件过滤
        List<EdgeEntity> secondLevelEdges = getEdgebyCondition(secondCondition, preSecondLevelEdges);




        //获取前置一级关系2：二级节点和一级中心节点的关系
        List<EdgeEntity> preFirstLevelEdge2 = new ArrayList<>();
        for (NodeEntity secondLevelNode : secondLevelNodes) {
            preFirstLevelEdge2.addAll(getNodeRelation(secondLevelNode.getId(), firstCenterNode.getId()));
        }
        //获取前置一级关系 = 前置一级关系1 + 前置一级关系2
        List<EdgeEntity> preFirstLevelEdge = new ArrayList<>();
        preFirstLevelEdge.addAll(preFirstLevelEdge1);
        preFirstLevelEdge.addAll(preFirstLevelEdge2);
        //获取一级关系，前置一级关系根据条件过滤
        List<EdgeEntity> firstLevelEdges = getEdgebyCondition(firstCondition, preFirstLevelEdge);



        //准备收尾工作
        GraphResultEntity resultEntity = new GraphResultEntity();
        firstLevelNodes.stream().forEach(node -> {node.setLevel(1); node.setType("circle"); node.setIsCenter(false);});
        secondLevelNodes.stream().forEach(node -> {node.setLevel(2); node.setType("circle"); node.setIsCenter(false);});
        firstLevelEdges.stream().forEach(edge -> {edge.setType("line");});
        secondLevelEdges.stream().forEach(edge -> {edge.setType("line");});

        firstCenterNode.setIsCenter(true);
        firstCenterNode.setLevel(0);
        firstCenterNode.setType("circle");
        secondCenterNode.setIsCenter(true);
        secondCenterNode.setLevel(1);
        secondCenterNode.setType("circle");

        //一级中心节点和二级中心节点需要添加到一级节点中
        firstLevelNodes.add(firstCenterNode);
        firstLevelNodes.add(secondCenterNode);
        //一级中心节点和二级中心节点关系需要添加到一级关系中
        firstCenterAndSecondCenterEdg.stream().forEach(edge -> edge.setType("line"));
        firstLevelEdges.addAll(firstCenterAndSecondCenterEdg);

        resultEntity.setFirstLevel(GraphLevelDataEntity.builder()
                .nodes(firstLevelNodes)
                .edges(firstLevelEdges)
                .build());
        resultEntity.setSecondLevel(GraphLevelDataEntity.builder()
                .nodes(secondLevelNodes)
                .edges(secondLevelEdges)
                .build());
        return resultEntity;
    }



    /**
     * 三级图谱查询
     * @param request
     * @return
     */
    private GraphResultEntity thirdLevelGraph(GraphRequest request) {
        //获取条件
        GraphLevelConditionsEntity firstCondition = request.getFirstLevel();
        GraphLevelConditionsEntity secondCondition = request.getSecondLevel();
        GraphLevelConditionsEntity thirdCondition = request.getThirdLevel();
        //准备图
        GraphEntitiy firstGraph = getDirectGraph(firstCondition.getNodeId());
        GraphEntitiy secondGraph = getDirectGraph(secondCondition.getNodeId());
        GraphEntitiy thirdGraph = getDirectGraph(thirdCondition.getNodeId());
        //准备关联节点和关联关系
        List<NodeEntity> firstCorrelationNodes = firstGraph.getNodes();
        List<NodeEntity> secondCorrelationNodes = secondGraph.getNodes();
        List<NodeEntity> thirdCorrelationNodes = thirdGraph.getNodes();
        List<EdgeEntity> firstCorrelationEdges = firstGraph.getEdges();
        List<EdgeEntity> secondCorrelationEdges = secondGraph.getEdges();
        List<EdgeEntity> thirdCorrelationEdges = thirdGraph.getEdges();
        //准备中心节点
        NodeEntity firstCenterNode = firstGraph.getCenterNode();
        NodeEntity secondCenterNode = secondGraph.getCenterNode();
        NodeEntity thirdCenterNode = thirdGraph.getCenterNode();
        //做准备中心节点间的关系
        List<EdgeEntity> firstCenterAndSecondCenterEdg = getNodeRelation(firstCenterNode.getId(), secondCenterNode.getId());
        List<EdgeEntity> secondCenterAndThirdCenterEdg = getNodeRelation(secondCenterNode.getId(), thirdCenterNode.getId());
        List<EdgeEntity> firstCenterAndThirdCenterEdg = getNodeRelation(firstCenterNode.getId(), thirdCenterNode.getId());



        /**
         * 准备前置的一级节点和一级关系，然后根据条件过滤获取真正的一级节点和一级关系
         * 步骤：
         *      前置一级节点 = 一级关联节点 - 二级中心节点 - 三级中心节点
         *              注意：由于一级节点可能和三级中心节点连接，例如李四同时属于一级中心节点和二级中心节点，但是李四是二级节点，因此李四可以作为三级中心节点
         *      一级节点 = 条件过滤前置一级节点
         *
         *
         *      前置一级关系 = 前置一级关系1 + 前置一级关系2 + 前置一级关系3
         *      前置一级关系1 = 一级关联关系 - 一级中心节点和二级中心节点的关系 - 一级中心节点和三级中心节点的关系
         *          注意：
         *              前置一级关系1需要根据一级节点过滤
         *      前置一级关系2 = 二级节点和一级中心节点的关系
         *      前置一级关系3 = 三级节点和一级中心节点的关系
         *      一级关系 = 前置一级关系根据条件过滤
         */
        //获取前置一级节点
        List<NodeEntity> preFirstLevelNodes = firstCorrelationNodes.stream().filter(node -> !node.getId().equals(secondCenterNode.getId()) && !node.getId().equals(thirdCenterNode.getId())).collect(Collectors.toList());
        //获取一级节点，根据条件过滤
        List<NodeEntity> firstLevelNodes = getNodebyCondition(firstCondition, preFirstLevelNodes);

        //获取前置一级关系1
        List<EdgeEntity> preFirstLevelEdge1 = firstCorrelationEdges.stream().filter(edge -> !firstCenterAndSecondCenterEdg.contains(edge) && !firstCenterAndThirdCenterEdg.contains(edge)).collect(Collectors.toList());
        //根据一级节点过滤前置一级关系1
        List<String> firstLevelNodeIds = firstLevelNodes.stream().map(node -> node.getId()).collect(Collectors.toList());
        preFirstLevelEdge1 = preFirstLevelEdge1.stream().filter(edge -> firstLevelNodeIds.contains(edge.getSource()) || firstLevelNodeIds.contains(edge.getTarget())).collect(Collectors.toList());



        /**
         * 准备前置二级节点和二级级关系，然后根据条件过滤获取真正的二级节点和二级关系
         * 步骤：
         *      前置二级节点 = 二级关联节点 - 一级中心节点 - 三级中心节点 - 一级节点
         *      二级节点 = 前置二级节点根据条件过滤
         *
         *      前置二级关系 = 前置二级关系1 + 前置二级关系2 + 前置二级关系3
         *      前置二级关系1 = 二级关联关系 - 一级中心节点和二级中心节点的关系 - 二级中心节点和三级中心节点的关系
         *      前置二级关系2 = 一级节点和二级中心节点的关系
         *      前置二级关系3 = 三级节点和二级中心节点的关系
         *      注意
         *          前置二级关系1需要根据二级节点过滤
         *      二级关系 = 前置二级关系根据条件过滤
         */
        // 获取前置二级节点
        List<NodeEntity> preSecondLevelNodes = secondCorrelationNodes.stream()
                .filter(node -> !node.getId().equals(firstCenterNode.getId())
                        && !node.getId().equals(thirdCenterNode.getId())
                        && !firstLevelNodes.contains(node))
                .collect(Collectors.toList());
        // 根据条件过滤，获取二级节点
        List<NodeEntity> secondLevelNodes = getNodebyCondition(secondCondition, preSecondLevelNodes);


        // 获取前置二级关系
        // 获取前置二级关系1 = 二级关联关系 - 一级中心节点和二级中心节点的关系 - 二级中心节点和三级中心节点的关系
        List<EdgeEntity> preSecondLevelEdge1 = secondCorrelationEdges.stream()
                .filter(edge -> !firstCenterAndSecondCenterEdg.contains(edge)
                        && !secondCenterAndThirdCenterEdg.contains(edge))
                .collect(Collectors.toList());
        // 根据二级节点过滤前置关系1
        List<String> secondLevelNodeIds = secondLevelNodes.stream().map(NodeEntity::getId).collect(Collectors.toList());
        preSecondLevelEdge1 = preSecondLevelEdge1.stream()
                .filter(edge -> secondLevelNodeIds.contains(edge.getSource()) || secondLevelNodeIds.contains(edge.getTarget()))
                .collect(Collectors.toList());
        // 前置关系2 = 二级节点和一级中心节点的关系
        List<EdgeEntity> preSecondLevelEdge2 = new ArrayList<>();
        for (NodeEntity secondLevelNode : secondLevelNodes) {
            preSecondLevelEdge2.addAll(getNodeRelation(secondLevelNode.getId(), firstCenterNode.getId()));
        }
        // 前置关系3 = 一级节点和二级中心节点的关系
        List<EdgeEntity> preSecondLevelEdge3 = new ArrayList<>();
        for (NodeEntity firstLevelNode : firstLevelNodes) {
            preSecondLevelEdge3.addAll(getNodeRelation(firstLevelNode.getId(), secondCenterNode.getId()));
        }

        // 合并所有前置二级关系
        List<EdgeEntity> preSecondLevelEdges = new ArrayList<>();
        preSecondLevelEdges.addAll(preSecondLevelEdge1);
        preSecondLevelEdges.addAll(preSecondLevelEdge2);
        preSecondLevelEdges.addAll(preSecondLevelEdge3);

        // 根据条件过滤二级关系
        List<EdgeEntity> secondLevelEdges = getEdgebyCondition(secondCondition, preSecondLevelEdges);



        //获取前置一级关系2：二级节点和一级中心节点的关系
        List<EdgeEntity> preFirstLevelEdge2 = new ArrayList<>();
        for (NodeEntity secondLevelNode : secondLevelNodes) {
            preFirstLevelEdge2.addAll(getNodeRelation(secondLevelNode.getId(), firstCenterNode.getId()));
        }




        /**
         * 准备前置三级节点和三级级关系，然后根据条件过滤获取真正的三级节点和三级关系
         * 步骤：
         *      前置三级节点 = 三级关联节点 - 一级中心节点 - 二级中心节点 - 一级节点 - 二级节点
         *      二级节点 = 前置二级节点根据条件过滤
         *
         *      前置三级关系 = 前置关系1 + 前置关系2 + 前置关系3
         *      前置三级关系1 = 三级关联关系 - 一级中心节点和三级中心节点的关系 - 二级中心节点和三级中心节点的关系
         *      前置三级关系2 = 一级节点和三级中心节点的关系
         *      前置三级关系3 = 二级节点和三级中心节点的关系
         *          注意：
         *              注意前置三级关系1需要根据三级节点过滤
         *      前置三级关系 = 前置二级关系根据条件过滤
         */
        // 获取前置三级节点
        List<NodeEntity> preThirdLevelNodes = thirdCorrelationNodes.stream()
                .filter(node -> !node.getId().equals(firstCenterNode.getId())
                        && !node.getId().equals(secondCenterNode.getId())
                        && !firstLevelNodes.contains(node)
                        && !secondLevelNodes.contains(node))
                .collect(Collectors.toList());

        // 根据条件过滤，获取三级节点
        List<NodeEntity> thirdLevelNodes = getNodebyCondition(thirdCondition, preThirdLevelNodes);

        // 获取前置三级关系
        // 前置关系1 = 三级关联关系 - 一级中心节点和三级中心节点的关系 - 二级中心节点和三级中心节点的关系
        List<EdgeEntity> preThirdLevelEdge1 = thirdCorrelationEdges.stream()
                .filter(edge -> !firstCenterAndThirdCenterEdg.contains(edge)
                        && !secondCenterAndThirdCenterEdg.contains(edge))
                .collect(Collectors.toList());

        // 根据三级节点过滤前置关系1
        List<String> thirdLevelNodeIds = thirdLevelNodes.stream().map(NodeEntity::getId).collect(Collectors.toList());
        preThirdLevelEdge1 = preThirdLevelEdge1.stream()
                .filter(edge -> thirdLevelNodeIds.contains(edge.getSource()) || thirdLevelNodeIds.contains(edge.getTarget()))
                .collect(Collectors.toList());

        // 前置关系2 = 三级节点和一级中心节点的关系
        List<EdgeEntity> preThirdLevelEdge2 = new ArrayList<>();
        for (NodeEntity thirdLevelNode : thirdLevelNodes) {
            preThirdLevelEdge2.addAll(getNodeRelation(thirdLevelNode.getId(), firstCenterNode.getId()));
        }

        // 前置关系3 = 三级节点和二级中心节点的关系
        List<EdgeEntity> preThirdLevelEdge3 = new ArrayList<>();
        for (NodeEntity thirdLevelNode : thirdLevelNodes) {
            preThirdLevelEdge3.addAll(getNodeRelation(thirdLevelNode.getId(), secondCenterNode.getId()));
        }

        // 前置关系4 = 一级节点和三级中心节点的关系 + 二级节点和三级中心节点的关系
        List<EdgeEntity> preThirdLevelEdge4 = new ArrayList<>();
        for (NodeEntity firstLevelNode : firstLevelNodes) {
            preThirdLevelEdge4.addAll(getNodeRelation(firstLevelNode.getId(), thirdCenterNode.getId()));
        }
        for (NodeEntity secondLevelNode : secondLevelNodes) {
            preThirdLevelEdge4.addAll(getNodeRelation(secondLevelNode.getId(), thirdCenterNode.getId()));
        }

        // 合并所有前置三级关系
        List<EdgeEntity> preThirdLevelEdges = new ArrayList<>();
        preThirdLevelEdges.addAll(preThirdLevelEdge1);
        preThirdLevelEdges.addAll(preThirdLevelEdge2);
        preThirdLevelEdges.addAll(preThirdLevelEdge3);
        preThirdLevelEdges.addAll(preThirdLevelEdge4);

        // 根据条件过滤三级关系
        List<EdgeEntity> thirdLevelEdges = getEdgebyCondition(thirdCondition, preThirdLevelEdges);

        // 根据三级节点过滤三级关系
        thirdLevelEdges = thirdLevelEdges.stream()
                .filter(edge -> thirdLevelNodeIds.contains(edge.getSource()) || thirdLevelNodeIds.contains(edge.getTarget()))
                .collect(Collectors.toList());








        //**************************************************************************
        //**************************************************************************
        //**************************************************************************
        //**************************************************************************
        //根据条件过滤，一级关系
        List<EdgeEntity> firstLevelEdges = getEdgebyCondition(firstCondition, preFirstLevelEdge1);















        //准备收尾工作
        firstLevelNodes.stream().forEach(node -> {node.setLevel(1); node.setType("circle"); node.setIsCenter(false);});
        secondLevelNodes.stream().forEach(node -> {node.setLevel(2); node.setType("circle"); node.setIsCenter(false);});
        thirdLevelNodes.stream().forEach(node -> {node.setLevel(3); node.setType("circle"); node.setIsCenter(false);});
        firstLevelEdges.stream().forEach(edge -> {edge.setType("line");});
        secondLevelEdges.stream().forEach(edge -> {edge.setType("line");});
        thirdLevelEdges.stream().forEach(edge -> {edge.setType("line");});

        firstCenterNode.setIsCenter(true);
        firstCenterNode.setLevel(0);
        firstCenterNode.setType("circle");
        secondCenterNode.setIsCenter(true);
        secondCenterNode.setLevel(1);
        secondCenterNode.setType("circle");
        thirdCenterNode.setIsCenter(true);
        thirdCenterNode.setLevel(2);
        thirdCenterNode.setType("circle");


        //一级中心节点和二级中心节点需要添加到一级节点中
        firstLevelNodes.add(firstCenterNode);
        firstLevelNodes.add(secondCenterNode);
        //三级中心节点需要添加到二级节点中
        secondLevelNodes.add(thirdCenterNode);

        //一级中心节点和二级中心节点的关系需要添加到一级关系中
        firstCenterAndSecondCenterEdg.stream().forEach(edge -> edge.setType("line"));
        firstLevelEdges.addAll(firstCenterAndSecondCenterEdg);
        //二级中心节点和三级中心节点的关系需要添加到二级关系中
        secondCenterAndThirdCenterEdg.stream().forEach(edge -> edge.setType("line"));
        secondLevelEdges.addAll(secondCenterAndThirdCenterEdg);


        //一级中心节点和三级中心节点的关系需要添加到一级关系中，存在问题
        firstCenterAndThirdCenterEdg.stream().forEach(edge -> edge.setType("line"));
        firstLevelEdges.addAll(firstCenterAndThirdCenterEdg);
        GraphResultEntity resultEntity = new GraphResultEntity();

        resultEntity.setFirstLevel(GraphLevelDataEntity.builder()
                .nodes(firstLevelNodes)
                .edges(firstLevelEdges)
                .build());
        resultEntity.setSecondLevel(GraphLevelDataEntity.builder()
                .nodes(secondLevelNodes)
                .edges(secondLevelEdges)
                .build());
        resultEntity.setThirdLevel(GraphLevelDataEntity.builder()
                .nodes(thirdLevelNodes)
                .edges(thirdLevelEdges)
                .build());
        return resultEntity;
    }


    /**
     * 根据条件筛选节点
     * @param condition
     * @param nodes
     */
    private List<NodeEntity> getNodebyCondition(GraphLevelConditionsEntity condition, List<NodeEntity> nodes){
        //获取筛选条件
        Integer nodeCount = condition.getNodeCount();
        Integer nodeType = condition.getNodeType();

        //获取级别节点
        List<NodeEntity> levelNodes = new ArrayList<>();
        List<NodeEntity> personNodes = nodes.stream().filter(node -> node.getLabel().equals(NodeTypeEnum.PERSON.getValue())).collect(Collectors.toList());
        List<NodeEntity> companyNodes = nodes.stream().filter(node -> node.getLabel().equals(NodeTypeEnum.COMPANY.getValue())).collect(Collectors.toList());

        if (NodeTypeEnum.fromKey(nodeType) == NodeTypeEnum.ALL) {
            // 计算每种类型需要保留的节点数
            int nodesPerType = nodeCount / 2;
            int remaining = nodeCount % 2; // 余数，用于补充到其中一种类型

            // 从personNodes中获取节点
            int personActual = Math.min(nodesPerType + remaining, personNodes.size());
            if (personActual > 0) {
                levelNodes.addAll(personNodes.subList(0, personActual));
            }

            // 从companyNodes中获取节点
            int companyActual = Math.min(nodesPerType, companyNodes.size());
            if (companyActual > 0) {
                levelNodes.addAll(companyNodes.subList(0, companyActual));
            }

            // 如果已获取的节点数不足，补充节点直到达到nodeCount
            int currentSize = levelNodes.size();
            if (currentSize < nodeCount) {
                // 先尝试从personNodes补充
                if (personActual < personNodes.size()) {
                    int needMore = nodeCount - currentSize;
                    int canAdd = Math.min(needMore, personNodes.size() - personActual);
                    levelNodes.addAll(personNodes.subList(personActual, personActual + canAdd));
                    currentSize = levelNodes.size();
                }

                // 再尝试从companyNodes补充
                if (companyActual < companyNodes.size() && currentSize < nodeCount) {
                    int needMore = nodeCount - currentSize;
                    int canAdd = Math.min(needMore, companyNodes.size() - companyActual);
                    levelNodes.addAll(companyNodes.subList(companyActual, companyActual + canAdd));
                }
            }
        } else if (NodeTypeEnum.fromKey(nodeType) == NodeTypeEnum.PERSON) {
            int personLimit = Math.min(nodeCount, personNodes.size());
            levelNodes.addAll(personNodes.subList(0, personLimit));
        } else if (NodeTypeEnum.fromKey(nodeType) == NodeTypeEnum.COMPANY) {
            int companyLimit = Math.min(nodeCount, companyNodes.size());
            levelNodes.addAll(companyNodes.subList(0, companyLimit));
        }
        return levelNodes;
    }

    /**
     * 根据条件筛选关系
     * @param condition
     * @param edges
     */
    private List<EdgeEntity> getEdgebyCondition(GraphLevelConditionsEntity condition, List<EdgeEntity> edges){
        //获取筛选条件
        List<String> relationships = condition.getRelationships();
        //获取一级关系
        List<EdgeEntity> levelEdges = edges.stream().filter(edge -> relationships.contains(edge.getLabel())).collect(Collectors.toList());
        return levelEdges;
    }


    /**
     * 替换式更新关系
     * 先删除指定的关系，再创建新的关系
     *
     * @param relationships 关系列表
     */
    private void updateRelationshipsWithReplace(List<Relationship> relationships) {
        // 1. 删除指定的关系
        deleteSpecifiedRelationshipsOnly(relationships);

        // 2. 创建新的关系
        for (Relationship relationship : relationships) {
            createRelationship(relationship);
        }
    }

    /**
     * 仅删除指定的关系（不删除节点）
     *
     * @param relationships 要删除的关系列表
     */
    private void deleteSpecifiedRelationshipsOnly(List<Relationship> relationships) {
        // 按关系类型分组
        Map<String, List<Relationship>> relsByType = relationships.stream()
                .collect(Collectors.groupingBy(Relationship::getType));

        for (Map.Entry<String, List<Relationship>> entry : relsByType.entrySet()) {
            String relType = entry.getKey();
            List<Relationship> relList = entry.getValue();

            String cypher = String.format(
                    "UNWIND $relsData as relData\n" +
                            "MATCH (a {nodeId: relData.startNodeId})-[r:%s]->(b {nodeId: relData.endNodeId})\n" +
                            "DELETE r",
                    relType);

            List<Map<String, Object>> relsData = relList.stream()
                    .map(rel -> {
                        Map<String, Object> data = new HashMap<>();
                        data.put("startNodeId", rel.getStartNodeId());
                        data.put("endNodeId", rel.getEndNodeId());
                        return data;
                    })
                    .collect(Collectors.toList());

            Map<String, Object> parameters = new HashMap<>();
            parameters.put("relsData", relsData);

            try {
                neo4jClient.query(cypher)
                        .bindAll(parameters)
                        .run();
            } catch (Exception e) {
                log.warn("删除关系失败: type={}, error={}", relType, e.getMessage());
            }
        }
    }


    /**
     * 准备节点数据
     *
     * @param node 节点对象
     * @return 节点数据Map
     */
    private Map<String, Object> prepareNodeData(Node node) {
        Map<String, Object> nodeData = new HashMap<>();
        nodeData.put("nodeId", node.getProperties().get("nodeId"));
        nodeData.put("properties", node.getProperties());
        return nodeData;
    }


    @Transactional
    public Map<String, Object> createNode(CreateGraphRequest request) {
        Map<String, Object> result = new HashMap<>();
        try {
            // 创建节点
            for (Node node : request.getNodes()) {
                createNode(node);
            }
            result.put("success", true);
            result.put("message", "图数据创建成功");
            result.put("nodeCount", request.getNodes().size());
        } catch (Exception e) {
            throw new RuntimeException("图数据创建失败: " + e.getMessage(), e);
        }
        return result;
    }


    @Transactional
    public Map<String, Object> createRelationships(CreateGraphRequest request) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 创建关系
            for (Relationship relationship : request.getRelationships()) {
                createRelationship(relationship);
            }
            result.put("success", true);
            result.put("message", "图数据创建成功");
            result.put("relationshipCount", request.getRelationships().size());
        } catch (Exception e) {
            throw new RuntimeException("图数据创建失败: " + e.getMessage(), e);
        }

        return result;
    }


    private void createNode(Node node) {
        StringBuilder cypher = new StringBuilder("CREATE (n:");
        cypher.append(node.getType()).append(" $props)");

        Map<String, Object> parameters = new HashMap<>();
        parameters.put("props", node.getProperties());

        neo4jClient.query(cypher.toString())
                .bindAll(parameters)
                .run();
    }


    private void createRelationship(Relationship relationship) {
        String cypher = String.format(
                "MATCH (a) WHERE a.nodeId = $startNodeId\n" +
                        "MATCH (b) WHERE b.nodeId = $endNodeId\n" +
                        "CREATE (a)-[r:%s $props]->(b)",
                relationship.getType());

        Map<String, Object> parameters = new HashMap<>();
        String startNodeId = relationship.getStartNodeId();
        String endNodeId = relationship.getEndNodeId();
        Map<String, Object> properties = relationship.getProperties();

        parameters.put("startNodeId", startNodeId);
        parameters.put("endNodeId", endNodeId);
        properties.put("startNodeId", startNodeId);
        properties.put("endNodeId", endNodeId);
        parameters.put("props", properties != null ? properties : new HashMap<>());

        neo4jClient.query(cypher)
                .bindAll(parameters)
                .run();
    }



    private GraphEntitiy convertToGraphDTO(Map<String, Object> resultMap) {
        if (resultMap == null || resultMap.isEmpty()) {
            return new GraphEntitiy();
        }
        // 将Map转换为JSON字符串
        String jsonString = JSON.toJSONString(resultMap);

        // 使用Fastjson直接转换为目标对象
        GraphEntitiy dto = JSON.parseObject(jsonString, GraphEntitiy.class);
        return dto;
    }


    private List<EdgeEntity> convertToRelationsDTO(List<Map<String, Object>> resultMap) {
        if (resultMap == null || resultMap.isEmpty()) {
            return new ArrayList<>();
        }
        List<EdgeEntity> edgeEntities = new ArrayList<>();
        for (Map<String, Object> relationMap : resultMap) {
            //Map转换成JSON字符串
            String jsonString = JSON.toJSONString(relationMap);
            // 使用Fastjson直接转换为目标对象
            EdgeEntity edgeEntity = JSON.parseObject(jsonString, EdgeEntity.class);
            edgeEntities.add(edgeEntity);
        }
        return edgeEntities;
    }



    //    /**
//     * 二级图谱查询
//     * @param request
//     * @return
//     */
//    private GraphResultEntity secondLevelGraph(GraphRequest request) {
//        //获取条件
//        GraphLevelConditionsEntity firstCondition = request.getFirstLevel();
//        GraphLevelConditionsEntity secondCondition = request.getSecondLevel();
//        //准备图
//        GraphEntitiy firstGraph = getDirectGraph(firstCondition.getNodeId());
//        GraphEntitiy secondGraph = getDirectGraph(secondCondition.getNodeId());
//        //准备一级和二级的关联节点和关联关系
//        List<NodeEntity> firstCorrelationNodes = firstGraph.getNodes();
//        List<NodeEntity> secondCorrelationNodes = secondGraph.getNodes();
//        List<EdgeEntity> firstCorrelationEdges = firstGraph.getEdges();
//        List<EdgeEntity> secondCorrelationEdges = secondGraph.getEdges();
//        //准备一级中心节点和二级中心节点
//        NodeEntity firstCenterNode = firstGraph.getCenterNode();
//        NodeEntity secondCenterNode = secondGraph.getCenterNode();
//
//
//        /**
//         * 准备前置的一级节点和一级关系，然后根据条件过滤获取真正的一级节点和一级关系
//         * 前置一级节点 = 一级关联节点 - 二级中心节点
//         * 前置一级关系 = 一级关联关系 - 一级中心节点和二级中心节点的关系
//         */
//        //获取前置一级节点和一级关系
//        List<NodeEntity> preFirstLevelNodes = firstCorrelationNodes.stream().filter(node -> !node.getId().equals(secondCenterNode.getId())).collect(Collectors.toList());
//        List<EdgeEntity> firstCenterAndSecondCenterEdg = getNodeRelation(firstCenterNode.getId(), secondCenterNode.getId());
//        List<EdgeEntity> preFirstLevelEdges = firstCorrelationEdges.stream().filter(edge -> !firstCenterAndSecondCenterEdg.contains(edge)).collect(Collectors.toList());
//        //根据条件过滤，获取一级节点和一级关系
//        List<NodeEntity> firstLevelNodes = getNodebyCondition(firstCondition, preFirstLevelNodes);
//        List<EdgeEntity> firstLevelEdges = getEdgebyCondition(firstCondition, preFirstLevelEdges);
//        //根据一级节点过滤一级关系
//        List<String> firstLevelNodeIds = firstLevelNodes.stream().map(node -> node.getId()).collect(Collectors.toList());
//        firstLevelEdges = firstLevelEdges.stream().filter(edge -> firstLevelNodeIds.contains(edge.getSource()) || firstLevelNodeIds.contains(edge.getTarget())).collect(Collectors.toList());
//
//
//        /**
//         * 准备前置二级节点和二级级关系，然后根据条件过滤获取真正的二级节点和二级关系
//         * 步骤：
//         *      前置二级节点 = 二级关联节点 - 一级中心节点 - 一级节点
//         *      二级节点 = 前置二级节点根据条件过滤
//         *
//         *      前置二级关系 = 前置关系1 + 前置关系2 + 前置关系3
//         *      前置关系1 = 二级关联关系 - 一级中心节点和二级中心节点的关系，注意前置关系1根据二级节点过滤
//         *      前置关系2 = 二级节点和一级中心节点的关系
//         *      前置关系3 = 一级节点和二级中心节点的关系
//         *      二级关系 = 前置二级关系根据条件过滤
//         * 注意：
//         *      1.前置关系1需要根据二级节点过滤，因为前置关系1是二级关联关系，但是该部分的关系需要二级节点匹配，因此需要根据二级节点过滤
//         */
//        //获取前置二级节点
//        List<NodeEntity> preSecondLevelNodes = secondCorrelationNodes.stream().filter(node -> !node.getId().equals(firstCenterNode.getId()) && !firstLevelNodes.contains(node)).collect(Collectors.toList());
//        //根据条件过滤，获取二级节点
//        List<NodeEntity> secondLevelNodes = getNodebyCondition(secondCondition, preSecondLevelNodes);
//
//        //获取前置二级关系
//        //获取前置关系1, = 获取二级关联关系 - 一级中心节点和二级中心节点的关系
//        List<EdgeEntity> preSecondLevelEdge1 = secondCorrelationEdges.stream().filter(edge -> !firstCenterAndSecondCenterEdg.contains(edge)).collect(Collectors.toList());
//        //根据二级节点过滤前置1关系
//        List<String> secondLevelNodeIds = secondLevelNodes.stream().map(node -> node.getId()).collect(Collectors.toList());
//        preSecondLevelEdge1 = preSecondLevelEdge1.stream().filter(edge -> secondLevelNodeIds.contains(edge.getSource()) || secondLevelNodeIds.contains(edge.getTarget())).collect(Collectors.toList());
//        //获取前置关系2：二级节点和一级中心节点的关系
//        List<EdgeEntity> preSecondLevelEdge2 = new ArrayList<>();
//        for (NodeEntity secondLevelNode : secondLevelNodes) {
//            preSecondLevelEdge2.addAll(getNodeRelation(secondLevelNode.getId(), firstCenterNode.getId()));
//        }
//        //获取前置关系3：一级节点和二级中心节点的关系
//        List<EdgeEntity> preSecondLevelEdge3 = new ArrayList<>();
//        for (NodeEntity firstLevelNode : firstLevelNodes) {
//            preSecondLevelEdge3.addAll(getNodeRelation(firstLevelNode.getId(), secondCenterNode.getId()));
//        }
//        List<EdgeEntity>  preSecondLevelEdges = new ArrayList<>();
//        preSecondLevelEdges.addAll(preSecondLevelEdge1);
//        preSecondLevelEdges.addAll(preSecondLevelEdge2);
//        preSecondLevelEdges.addAll(preSecondLevelEdge3);
//        //前置关系根据条件过滤
//        List<EdgeEntity> secondLevelEdges = getEdgebyCondition(secondCondition, preSecondLevelEdges);
//
//
//        GraphResultEntity resultEntity = new GraphResultEntity();
//
//        //准备收尾工作
//        firstLevelNodes.stream().forEach(node -> {node.setLevel(1); node.setType("circle"); node.setIsCenter(false);});
//        secondLevelNodes.stream().forEach(node -> {node.setLevel(2); node.setType("circle"); node.setIsCenter(false);});
//        firstLevelEdges.stream().forEach(edge -> {edge.setType("line");});
//        secondLevelEdges.stream().forEach(edge -> {edge.setType("line");});
//
//        firstCenterNode.setIsCenter(true);
//        firstCenterNode.setLevel(0);
//        firstCenterNode.setType("circle");
//        secondCenterNode.setIsCenter(true);
//        secondCenterNode.setLevel(1);
//        secondCenterNode.setType("circle");
//
//        //一级中心节点和二级中心节点需要添加到一级节点中
//        firstLevelNodes.add(firstCenterNode);
//        firstLevelNodes.add(secondCenterNode);
//        //一级中心节点和二级中心节点关系需要添加到一级关系中
//        firstCenterAndSecondCenterEdg.stream().forEach(edge -> edge.setType("line"));
//        firstLevelEdges.addAll(firstCenterAndSecondCenterEdg);
//
//        resultEntity.setFirstLevel(GraphLevelDataEntity.builder()
//                .nodes(firstLevelNodes)
//                .edges(firstLevelEdges)
//                .build());
//        resultEntity.setSecondLevel(GraphLevelDataEntity.builder()
//                .nodes(secondLevelNodes)
//                .edges(secondLevelEdges)
//                .build());
//        return resultEntity;
//    }
}